home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -coverdisks- / af108a / ifx / prefs / v1_gt / ifx.e < prev    next >
Text File  |  1998-01-17  |  27KB  |  1,118 lines

  1. ->
  2. -> prefs.e
  3. ->
  4. -> An attempt at using GadTools to do the IFX preferences 
  5. -> program.
  6. ->
  7.  
  8. -> Modules
  9. MODULE 'dos',        'dos/dos',        'dos/dosextens',    'dos/dostags'
  10. MODULE 'asl',        'libraries/asl'
  11. MODULE 'intuition', 'intuition/intuition', 'intuition/gadgetclass',
  12.         'intuition/screens'
  13. MODULE 'graphics',  'graphics/text'
  14. MODULE 'gadtools',  'libraries/gadtools'
  15. MODULE 'exec/ports'
  16. MODULE 'utility/tagitem'
  17.  
  18. MODULE 'exec/obj/list',     'exec/obj/node'
  19. MODULE 'other/split'
  20. MODULE '*/modules/action'
  21. MODULE 'amigalib/tasks'
  22. MODULE 'tools/sound'
  23. MODULE 'fabio/rxobj_oo'
  24.  
  25. ->
  26. -> Object definitions
  27. ->
  28.  
  29.     -> ID
  30.     
  31. OBJECT ifx_id OF node
  32.     list    :PTR TO list        -> Action list
  33. ENDOBJECT
  34.  
  35.     -> Action
  36.  
  37. OBJECT ifx_action OF node
  38.     type        :PTR TO CHAR
  39. ENDOBJECT
  40.     
  41. -> Gadget ID's
  42. ENUM LV_IDS,
  43.      LV_ACTS,
  44.      BUT_SAVE,
  45.      BUT_CANCEL,
  46.      BUT_ADDID,
  47.      BUT_REMID,
  48.      BUT_ADDACT,
  49.      BUT_REMACT,
  50.      BUT_OKAYID,
  51.      BUT_OKAYACT,
  52.      BUT_CANCELACT,
  53.      BUT_FILEREQ,
  54.      BUT_TESTACT,
  55.      STR_INFO,
  56.      STR_ID,
  57.      CY_TYPE,
  58.      ID_DUMMY
  59.  
  60.     -> Gadget objects
  61. DEF    lv_ids        :PTR TO gadget,
  62.     lv_acts        :PTR TO gadget,
  63.     but_save    :PTR TO gadget,
  64.     but_cancel    :PTR TO gadget,
  65.     but_okayid    :PTR TO gadget,
  66.     but_addid    :PTR TO gadget,
  67.     but_remid    :PTR TO gadget,
  68.     but_addact    :PTR TO gadget,
  69.     but_remact    :PTR TO gadget,
  70.     but_filereq    :PTR TO gadget,
  71.     but_testact    :PTR TO gadget,
  72.     str_info    :PTR TO gadget,
  73.     str_id        :PTR TO gadget,
  74.     cy_type        :PTR TO gadget,
  75.     but_okayact    :PTR TO gadget
  76.     
  77. -> Global variables
  78.     -> Font
  79. DEF topaz80:PTR TO textattr
  80.  
  81.     -> Sounds
  82. DEF sounds:PTR TO LONG, curr
  83.  
  84.     -> Ids
  85. DEF ids:PTR TO list
  86.  
  87.     -> Port
  88. DEF g_mp:PTR TO mp
  89.     
  90.     -> Current ID and Action
  91. DEF id_curr:PTR TO ifx_id, act_curr:PTR TO ifx_action
  92.  
  93.     -> Last directory name
  94. DEF last_dir:PTR TO CHAR
  95.  
  96. -> MAIN
  97. PROC main() HANDLE
  98.     DEF font
  99.     
  100.     -> Allocate sounds space
  101.     NEW sounds[2]
  102.     
  103.     -> Create our ids list
  104.     NEW ids.init()
  105.     IF ids=NIL THEN Throw("MEM", ' (for IDS list)')
  106.     
  107.     -> Create our global message port
  108.     g_mp := CreateMsgPort()
  109.     IF g_mp=NIL THEN Throw("INIT", ' (message port)')
  110.     
  111.     -> Load the configuration
  112.     IF load_config() THEN put_error('Unable to open prefs file.\n')
  113.     
  114.     -> Open ASL
  115.     IF aslbase=NIL THEN aslbase := OpenLibrary('asl.library', 37)
  116.     IF aslbase=NIL /* Still */ THEN RETURN FALSE
  117.     
  118.     -> Open Gadtools
  119.     IF gadtoolsbase=NIL THEN gadtoolsbase := OpenLibrary('gadtools.library', 37)
  120.     IF gadtoolsbase=NIL /* Still */ THEN RETURN FALSE
  121.     
  122.     -> Open Datatypes
  123.     IF datatypesbase=NIL THEN datatypesbase := OpenLibrary('datatypes.library', 0)
  124.     
  125.     -> Initialize some stuff
  126.     topaz80 := ['topaz.font', 8, 0, 0]:textattr            -> Default font
  127.     
  128.     -> Open the font, to make sure it's possible
  129.     IF (font := OpenFont(topaz80))<>NIL
  130.         -> Do the stuff
  131.         dowindow({maingadgets})
  132.         
  133.         -> Close the font
  134.         CloseFont(font)
  135.     ELSE
  136.         put_error('Unable to open topaz font!\n')
  137.     ENDIF    
  138.  
  139. EXCEPT DO
  140.     IF font            THEN CloseFont(font)
  141.     IF gadtoolsbase THEN CloseLibrary(gadtoolsbase)
  142.     gadtoolsbase := NIL
  143.     IF aslbase        THEN CloseLibrary(aslbase)
  144.     aslbase := NIL
  145.     IF datatypesbase THEN CloseLibrary(datatypesbase)
  146.     datatypesbase := NIL
  147.     IF sounds[0] THEN END sounds[0]
  148.     IF sounds[1] THEN END sounds[1]
  149. ENDPROC
  150.  
  151. PROC dowindow(makegadgets)
  152.     DEF myscr        :PTR TO screen,
  153.         mywin        :PTR TO window,
  154.         glist        :PTR TO gadget,
  155.         gad            :LONG,
  156.         userdata    :LONG,
  157.         done=0        :LONG,
  158.         vi            :LONG
  159.         
  160.  
  161.     -> Lock the public screen
  162.     IF (myscr := LockPubScreen(NIL))<>NIL
  163.         -> Get visual info
  164.         IF (vi := GetVisualInfoA(myscr, [TAG_END, NIL]))<>NIL
  165.             gad := makegadgets(myscr, vi, {glist})
  166.             IF gad
  167.                 -> Open the window
  168.                 IF (mywin := OpenWindowTagList(NIL,
  169.                         [WA_TITLE,        'IFX Preferences V2.00',
  170.                          WA_GADGETS,            glist,
  171.                          WA_AUTOADJUST,         TRUE,
  172.                          WA_WIDTH,                480,
  173.                          WA_INNERHEIGHT,        130,
  174.                          WA_DRAGBAR,            1,
  175.                          WA_CLOSEGADGET,        1,
  176.                          WA_DEPTHGADGET,        1,
  177.                          WA_ACTIVATE,            1,
  178.                          WA_SIMPLEREFRESH,        1,
  179.                          WA_IDCMP,            IDCMP_CLOSEWINDOW OR
  180.                                              IDCMP_REFRESHWINDOW OR
  181.                                              IDCMP_VANILLAKEY OR
  182.                                              LISTVIEWIDCMP OR
  183.                                              BUTTONIDCMP OR
  184.                                              STRINGIDCMP OR
  185.                                              CYCLEIDCMP,
  186.                          WA_PUBSCREEN,             myscr,
  187.                          NIL,                     NIL]))<>NIL
  188.                     
  189.                     -> Set userdata
  190.                     mywin.userdata := makegadgets
  191.  
  192.                     -> Refresh the gadgets
  193.                     Gt_RefreshWindow(mywin, NIL)
  194.                     
  195.                     WHILE done=NIL
  196.                         
  197.                         -> Do that gadget/message THANG..
  198.                         makegadgets := handlewindow(mywin, userdata)
  199.                         
  200.                         IF makegadgets
  201.                             -> Free up the old gadgets
  202.                             RemoveGList(mywin, glist, 0)
  203.                             FreeGadgets(glist)
  204.                             
  205.                             -> Make the new gadgets
  206.                             gad := makegadgets(myscr, vi, {glist})
  207.                             IF gad
  208.                                 -> Add the gadgets
  209.                                 AddGList( mywin, glist, -1, -1, NIL ) 
  210.                                 
  211.                                 -> Erase the old gadgets
  212.                                 EraseRect(mywin.rport, mywin.borderleft, mywin.bordertop, mywin.width-mywin.borderright-1, mywin.height-mywin.borderbottom-1)
  213.                                 
  214.                                 -> Draw the new ones
  215.                                 RefreshGadgets(glist, mywin, NIL)
  216.                                 
  217.                                 -> Refresh'em for fun!
  218.                                 Gt_RefreshWindow(mywin, NIL)
  219.                             ELSE
  220.                                 done := 1
  221.                             ENDIF
  222.                         ELSE
  223.                             done := 1
  224.                         ENDIF
  225.                     ENDWHILE
  226.                     
  227.                     -> Close the window
  228.                     CloseWindow(mywin)
  229.                  ELSE
  230.                      put_error('Unable to open window!\n')
  231.                  ENDIF
  232.             ELSE
  233.                 put_error('Unable to create gadgets!\n')
  234.             ENDIF
  235.                 FreeGadgets(glist)
  236.                 FreeVisualInfo(vi)
  237.         ELSE
  238.             put_error('Unable to get visual info!\n')
  239.             ENDIF
  240.             
  241.         UnlockPubScreen(NIL, myscr)
  242.     ELSE
  243.         put_error('Unable to lock public screen!\n')
  244.     ENDIF
  245. ENDPROC
  246.  
  247.  
  248. PROC handlewindow(win:PTR TO window, userdata)
  249.     DEF imsg:PTR TO intuimessage,
  250.         class, code, id, object, gad:PTR TO gadget,
  251.         ifx:PTR TO ifx_id, act:PTR TO ifx_action,
  252.         rx:PTR TO rxobj,
  253.         obj:PTR TO node,
  254.         thwin:PTR TO window,
  255.         asl:PTR TO filerequester,
  256.         temp:PTR TO CHAR,
  257.         done=NIL
  258.     
  259.     -> Set ourselves to global status
  260.     done
  261.     
  262.     WHILE done=NIL
  263.         WaitPort(win.userport)
  264.         WHILE (imsg := Gt_GetIMsg(win.userport))<>NIL
  265.             class  := imsg.class
  266.             code   := imsg.code
  267.             object := imsg.iaddress
  268.             thwin  := imsg.idcmpwindow
  269.             
  270.             SELECT class
  271.                 CASE IDCMP_REFRESHWINDOW
  272.                     -> Refresh the window and its gadgets
  273.                     Gt_BeginRefresh(thwin)
  274.                     Gt_EndRefresh(thwin, 1)
  275.                 
  276.                 CASE IDCMP_GADGETDOWN
  277.                 CASE IDCMP_MOUSEMOVE
  278.                 CASE IDCMP_GADGETUP
  279.                     gad := object
  280.                     id := gad.gadgetid
  281.                     
  282.                     gadgethit:
  283.                     
  284.                     SELECT id
  285.                         CASE LV_IDS
  286.                             IF lv_ids THEN killlist(lv_ids, win)
  287.                             id_curr := entrynum(ids, code)
  288.                             done := {idgadgets}
  289.                             
  290.                         CASE LV_ACTS
  291.                             IF id_curr
  292.                                 IF lv_acts THEN killlist(lv_acts, win)
  293.                                 act_curr := entrynum(id_curr.list, code)
  294.                                 done := {actgadgets}
  295.                             ENDIF
  296.                             
  297.                         CASE BUT_SAVE
  298.                             -> Save the config
  299.                             save_config()
  300.                             
  301.                             -> Inform IFX
  302.                             NEW rx.rxobj('IFXPREFS')
  303.                             rx.send('PLAY', 'prefs', NIL, NIL)
  304.                             END rx
  305.                             done := -1
  306.                              
  307.                         CASE BUT_CANCEL
  308.                             IF ask('Are you sure you want\nto exit without saving?', win)
  309.                                 -> Yes
  310.                                 done := -1
  311.                             ELSE
  312.                                 -> No
  313.                             ENDIF    
  314.                         
  315.                         CASE BUT_OKAYID
  316.                             IF id_curr AND str_id
  317.                                 -> Read the new string
  318.                                 END id_curr.name
  319.                                 
  320.                                 obj := str_id.specialinfo::stringinfo.buffer
  321.                                 IF obj
  322.                                     NEW id_curr.name[StrLen(obj)+1]
  323.                                     StrCopy(id_curr.name, obj)
  324.                                 ENDIF
  325.                                 
  326.                                 -> Nullify the id
  327.                                 id_curr := NIL
  328.                             ELSE
  329.                                 put_error('DEBUG: Error @ 289')
  330.                             ENDIF
  331.                             done := {maingadgets}
  332.  
  333.                         CASE BUT_ADDID
  334.                             killlist(lv_ids, win)
  335.                             id_curr := newid('new_id')
  336.                             IF id_curr
  337.                                 done := {idgadgets}
  338.                             ELSE
  339.                                 put_error('Unable to create new ID!')
  340.                             ENDIF
  341.                             
  342.                         CASE BUT_REMID
  343.                             IF id_curr
  344.                                 IF ask('Are you sure you want to\nremove this ID?', win)
  345.                                     -> Yes
  346.                                     END id_curr
  347.                                     id_curr := NIL
  348.                                     done := {maingadgets}
  349.                                 ENDIF
  350.                             ELSE
  351.                                 put_error('DEBUG: Error 274')
  352.                             ENDIF
  353.                             
  354.                         CASE BUT_ADDACT
  355.                             IF id_curr
  356.                                 -> Clear old list (not destroy)
  357.                                 IF lv_ids THEN killlist(lv_ids, win)
  358.                                 
  359.                                 -> Create new action
  360.                                 NEW act_curr
  361.                                 IF act_curr
  362.                                     id_curr.list.addtail(act_curr)
  363.                                     done := {actgadgets}
  364.                                 ELSE
  365.                                     put_error('Unable to create new Action.\n')
  366.                                 ENDIF
  367.                             ELSE
  368.                                 put_error('DEBUG: Error 286')
  369.                             ENDIF
  370.                             
  371.                         CASE BUT_REMACT
  372.                             IF act_curr
  373.                                 act_curr.remove()
  374.                                 END act_curr
  375.                                 act_curr := NIL
  376.                                 done := {idgadgets}
  377.                             ENDIF
  378.                         
  379.                         CASE BUT_OKAYACT
  380.                             IF act_curr AND str_info
  381.                                 -> Read the new string
  382.                                 END act_curr.name
  383.                                 
  384.                                 obj := str_info.specialinfo::stringinfo.buffer
  385.                                 IF obj
  386.                                     NEW act_curr.name[(StrLen(obj)+1)]
  387.                                     IF act_curr.name
  388.                                         CopyMem(obj, act_curr.name, StrLen(obj)+1)
  389.                                     ENDIF
  390.                                 ENDIF
  391.                                 
  392.                                 -> Nullify the action
  393.                                 act_curr := NIL
  394.                                 -> Go back to the ID window
  395.                                 done := {idgadgets}
  396.                             ELSE
  397.                                 put_error('DEBUG: Error @ 330')
  398.                             ENDIF
  399.                         
  400.                         CASE BUT_FILEREQ
  401.                             -> If there is a string in the gadget, we'll
  402.                             -> use it for our drawer
  403.                             obj := str_info.specialinfo::stringinfo.buffer
  404.                             IF obj
  405.                                 IF StrLen(obj)>1
  406.                                     -> Allocate memory
  407.                                     NEW id[StrLen(obj)+2]
  408.                                     
  409.                                     -> Copy it
  410.                                     StrCopy(id, obj)
  411.                                     
  412.                                     -> Slash the file part
  413.                                     temp := PathPart(id)
  414.                                     temp[] := "\0"
  415.                                 ELSE
  416.                                     id := last_dir
  417.                                     temp := NIL
  418.                                 ENDIF
  419.                             ELSE
  420.                                 id := last_dir
  421.                                 temp := NIL
  422.                             ENDIF
  423.                             
  424.                             -> Create the request
  425.                             asl := AllocAslRequest(ASL_FILEREQUEST,
  426.                                     [ASL_HAIL,            'Select A File',
  427.                                      ASL_WINDOW,        win,
  428.                                      ASL_LEFTEDGE,        win.leftedge,
  429.                                      ASL_TOPEDGE,        win.topedge,
  430.                                      ASL_WIDTH,            win.width,
  431.                                      ASL_HEIGHT,        win.height,
  432.                                      ASL_DIR,            IF id THEN id ELSE '',
  433.                                      ASL_FILE,            IF temp THEN temp ELSE '',
  434.                                      NIL,                NIL])
  435.                                 
  436.                             -> If successful
  437.                             IF asl
  438.                                 IF RequestFile(asl)<>NIL
  439.                                     -> asl.drawer and asl.file are the strings
  440.                                     NEW temp[StrLen(asl.file) + StrLen(asl.drawer)+1]
  441.                                     IF temp
  442.                                         IF AddPart(temp, asl.drawer, ALL)
  443.                                         IF AddPart(temp, asl.file, ALL)
  444.                                         -> Save dir for later use
  445.                                             IF asl.drawer
  446.                                                 END last_dir
  447.                                                 NEW last_dir[StrLen(asl.drawer)+1]
  448.                                                 IF last_dir
  449.                                                     StrCopy(last_dir, asl.drawer)
  450.                                                 ELSE
  451.                                                     put_error('Out of memory @ 443')
  452.                                                 ENDIF
  453.                                             ENDIF
  454.                                             
  455.                                             -> Set gadget, where we'll read it from later
  456.                                             Gt_SetGadgetAttrsA(str_info, win, NIL,
  457.                                                 [GTST_STRING,         temp,
  458.                                                  NIL,                NIL])
  459.                                                  
  460.                                         ENDIF
  461.                                         ENDIF
  462.                                         END temp
  463.                                     ELSE
  464.                                         put_error('Out of memory for string!')
  465.                                     ENDIF
  466.                                 ENDIF
  467.                                 FreeAslRequest(asl)
  468.                             ENDIF
  469.                         
  470.                         CASE BUT_TESTACT
  471.                             IF lv_acts THEN killlist(lv_acts, win)
  472.                             IF act_curr
  473.                                 temp := str_info.specialinfo::stringinfo.buffer
  474.                                 IF temp
  475.                                     -> Destroy old
  476.                                     END act_curr.name
  477.                                     
  478.                                     -> Make new
  479.                                     NEW act_curr.name[StrLen(temp)+1]
  480.                                     IF act_curr.name
  481.                                         CopyMem(temp, act_curr.name, StrLen(temp)+1)
  482.                                         do_action(act_curr)
  483.                                     ELSE
  484.                                         put_error('Out of memory @ 446', win)
  485.                                         done := -1
  486.                                     ENDIF
  487.                                 ENDIF
  488.                             ENDIF
  489.                             
  490.                         CASE CY_TYPE
  491.                             IF act_curr
  492.                                 SELECT code
  493.                                     CASE 0    -> "Sound"
  494.                                         act_curr.type := ACT_SOUNDFILE
  495.                                     CASE 1    -> "Executable"
  496.                                         act_curr.type := ACT_EXECUTE
  497.                                     CASE 2    -> "Other ID"
  498.                                         act_curr.type := ACT_IFX
  499.                                     CASE 3  -> "Nothing"
  500.                                         act_curr.type := ACT_NOTHING
  501.                                 ENDSELECT
  502.                             ELSE
  503.                                 put_error('DEBUG: Error @ 337')
  504.                             ENDIF
  505.                             
  506.                         CASE STR_INFO
  507.                         CASE STR_ID
  508.                     ENDSELECT
  509.                 
  510.                 CASE IDCMP_VANILLAKEY
  511.                     SELECT code
  512.                         CASE "n" -> New ID
  513.                             id := BUT_ADDID
  514.                         CASE "a" -> Add action
  515.                             id := BUT_ADDACT
  516.                         CASE "r" -> Remove ID
  517.                             id := BUT_REMID
  518.                         CASE "k" -> Keep ID
  519.                             id := BUT_OKAYID
  520.                         CASE "d" -> Delete Action
  521.                             id := BUT_REMACT
  522.                         CASE "s" -> Save
  523.                             id := BUT_SAVE
  524.                         CASE "c" -> Cancel Save
  525.                             id := BUT_CANCEL
  526.                         CASE "t"
  527.                             id := BUT_TESTACT
  528.                         DEFAULT
  529.                             id := NIL
  530.                     ENDSELECT
  531.                     IF id THEN JUMP gadgethit
  532.                     
  533.                 CASE IDCMP_CLOSEWINDOW
  534.                     IF ask('Do you really want\nto quit?  Your prefs\nwill not be saved!', win)
  535.                         done := -1
  536.                     ENDIF
  537.             ENDSELECT
  538.             
  539.             -> Loop to next message
  540.         ENDWHILE
  541.     ENDWHILE
  542.     
  543.     -> Set up the ID name when the screen goes off of it
  544.     IF id_curr AND (done = {actgadgets})
  545.         -> Read the new string
  546.         IF id_curr.name THEN END id_curr.name
  547.         
  548.         IF str_id
  549.             obj := str_id.specialinfo::stringinfo.buffer
  550.             IF obj
  551.                 NEW id_curr.name[StrLen(obj)+1]
  552.                 IF id_curr.name
  553.                     CopyMem(obj, id_curr.name, StrLen(obj)+1)
  554.                 ELSE
  555.                     put_error('Out of memory @ 517', win)
  556.                 ENDIF
  557.             ELSE
  558.                 put_error('Missing string @ 520', win)
  559.             ENDIF
  560.         ENDIF
  561.     ENDIF
  562.     
  563.     -> Check for total exit
  564.     IF done=-1 THEN RETURN NIL
  565.     
  566. ENDPROC done
  567.  
  568. PROC maingadgets(scr:PTR TO screen, vi, glistptr)
  569.     DEF ng:PTR TO newgadget,
  570.         gad:PTR TO gadget,
  571.         topborder
  572.         
  573.         -> Allocate the memory
  574.         NEW ng
  575.         
  576.         -> Get the top border size
  577.         topborder := scr.wbortop + scr.font.ysize + 4
  578.         
  579.         -> Create the context
  580.         gad := CreateContext(glistptr)
  581.         
  582.         -> Create the listview gadget
  583.         ng.leftedge := scr.wborleft+2
  584.         ng.topedge  := topborder
  585.         ng.width    := 480-scr.wborleft-scr.wborright-2
  586.             ng.height    := 85
  587.         ng.gadgettext := ''
  588.         ng.textattr := topaz80
  589.         ng.gadgetid := LV_IDS
  590.         ng.flags    := NIL
  591.         ng.visualinfo := vi
  592.         ng.userdata := NIL            -> TODO
  593.         
  594.         lv_ids := gad := CreateGadgetA(LISTVIEW_KIND, gad, ng,
  595.             [GTLV_LABELS,        ids,
  596.              NIL,                NIL])
  597.              
  598.         -> Create the "Add" button
  599.         ng.topedge    := ng.topedge + ng.height + 5
  600.         ng.height    := 15
  601.         ng.gadgettext := '_New'
  602.         ng.gadgetid    := BUT_ADDID
  603.         ng.userdata := NIL            -> TODO
  604.         
  605.         but_addid := gad := CreateGadgetA(BUTTON_KIND, gad, ng,
  606.             [GT_UNDERSCORE,        "_",
  607.              NIL,                NIL])
  608.         
  609.         -> Create the "Cancel" button
  610.         ng.topedge    := ng.topedge + ng.height + 5
  611.         ng.leftedge := ng.leftedge + ng.width
  612.         ng.width    := (ng.width/2)-10
  613.         ng.leftedge := ng.leftedge - ng.width
  614.         ng.gadgettext := '_Cancel'
  615.         ng.gadgetid    := BUT_CANCEL
  616.         ng.userdata := NIL            -> TODO
  617.         
  618.         but_cancel := gad := CreateGadgetA(BUTTON_KIND, gad, ng,
  619.                 [GT_UNDERSCORE,        "_",
  620.                  NIL,                NIL])
  621.  
  622.         -> Create the "Save" button
  623.         ng.leftedge := scr.wborleft+2
  624.         ng.gadgettext := '_Save'
  625.         ng.gadgetid := BUT_SAVE
  626.         ng.userdata := NIL            -> TODO
  627.         but_save := gad := CreateGadgetA(BUTTON_KIND, gad, ng,
  628.                 [GT_UNDERSCORE,        "_",
  629.                  NIL,                NIL])
  630.  
  631. ENDPROC gad, NIL
  632.  
  633. PROC idgadgets(scr:PTR TO screen, vi, glistptr)
  634.     DEF ng:PTR TO newgadget,
  635.         gad:PTR TO gadget,
  636.         topborder
  637.         
  638.         -> Allocate the memory
  639.         NEW ng
  640.         
  641.         -> Get the top border size
  642.         topborder := scr.wbortop + scr.font.ysize + 4
  643.         
  644.         -> Create the context
  645.         gad := CreateContext(glistptr)
  646.         
  647.         -> Create the listview gadget
  648.         ng.leftedge := scr.wborleft+2
  649.         ng.topedge  := topborder
  650.         ng.width    := 480-scr.wborleft-scr.wborright-2
  651.         ng.height    := 65
  652.         ng.gadgettext := ''
  653.         ng.textattr := topaz80
  654.         ng.gadgetid := LV_ACTS
  655.         ng.flags    := NIL
  656.         ng.visualinfo := vi
  657.         ng.userdata := id_curr
  658.         
  659.         lv_acts := gad := CreateGadgetA(LISTVIEW_KIND, gad, ng,
  660.             [GTLV_LABELS,        id_curr.list,
  661.              NIL,                NIL])
  662.         
  663.         -> Create the ID name entry string
  664.         ng.topedge        := ng.topedge + ng.height + 5
  665.         ng.height        := 15
  666.         ng.gadgetid        := STR_ID
  667.         str_id := gad := CreateGadgetA(STRING_KIND, gad, ng,
  668.             [GT_UNDERSCORE,            "_",
  669.              GTST_STRING,            id_curr.name,
  670.              GTST_MAXCHARS,            256,
  671.              NIL,                    NIL])
  672.      
  673.         -> Create the "Add" button
  674.         ng.topedge        := ng.topedge + ng.height + 5
  675.         ng.height        := 15
  676.         ng.gadgettext    := '_Add an Action'
  677.         ng.gadgetid        := BUT_ADDACT
  678.         
  679.         but_addact := gad := CreateGadgetA(BUTTON_KIND, gad, ng,
  680.             [GT_UNDERSCORE,        "_",
  681.              NIL,                NIL])
  682.         
  683.         -> Create the "OK" button
  684.         ng.topedge        := ng.topedge + ng.height + 5
  685.         ng.gadgettext    := '_Keep this'
  686.         ng.gadgetid        := BUT_OKAYID
  687.         ng.width        := (ng.width/3)
  688.         but_okayid := gad := CreateGadgetA(BUTTON_KIND, gad, ng,
  689.             [GT_UNDERSCORE,     "_",
  690.              NIL,                NIL])
  691.              
  692.         
  693.         -> Create the "Remove" Button
  694.         ng.gadgettext    := '_Remove This ID'
  695.         ng.gadgetid        := BUT_REMID
  696.         ng.leftedge        := ng.leftedge + (2*ng.width)
  697.         but_remid := gad := CreateGadgetA(BUTTON_KIND, gad, ng,
  698.             [GT_UNDERSCORE,        "_",
  699.              NIL,                NIL])
  700.         
  701. ENDPROC gad, lv_acts
  702.  
  703. PROC actgadgets(scr:PTR TO screen, vi, glistptr)
  704.     DEF ng:PTR TO newgadget,
  705.         gad:PTR TO gadget,
  706.         typenum,
  707.         topborder
  708.         
  709.         typenum := act_curr.type
  710.         SELECT typenum
  711.             CASE ACT_SOUND
  712.                 typenum := 0
  713.             CASE ACT_SOUNDFILE
  714.                 typenum := 0
  715.             CASE ACT_EXECUTE
  716.                 typenum := 1
  717.             CASE ACT_IFX
  718.                 typenum := 2
  719.             CASE ACT_NOTHING
  720.                 typenum := 3
  721.         ENDSELECT
  722.         
  723.         -> Allocate the memory
  724.         NEW ng
  725.         
  726.         -> Get the top border size
  727.         topborder := scr.wbortop + scr.font.ysize + 4
  728.         
  729.         -> Create the context
  730.         gad := CreateContext(glistptr)
  731.         
  732.         -> Create the cycle gadget
  733.         ng.leftedge := scr.wborleft+2
  734.         ng.topedge  := topborder
  735.         ng.width    := 480-scr.wborleft-scr.wborright-2
  736.         ng.height    := 15
  737.         ng.gadgettext := '_Type'
  738.         ng.textattr := topaz80
  739.         ng.gadgetid := CY_TYPE
  740.         ng.flags    := NIL
  741.         ng.visualinfo := vi
  742.         ng.userdata := act_curr            -> TODO
  743.         cy_type := gad := CreateGadgetA(CYCLE_KIND, gad, ng,
  744.             [GTCY_LABELS,        ['Sound', 'Command', 'Other ID', 'Do Nothing', NIL],
  745.              GTCY_ACTIVE,        typenum,
  746.              NIL,                NIL])
  747.         
  748.         -> Create the string gadget
  749.         ng.topedge         := ng.topedge + 20
  750.         ng.gadgettext    := '_Info'
  751.         ng.gadgetid        := STR_INFO
  752.         str_info := gad := CreateGadgetA(STRING_KIND, gad, ng,
  753.             [GT_UNDERSCORE,            "_",
  754.              GTST_STRING,            act_curr.name,
  755.              GTST_MAXCHARS,            512,
  756.              NIL,                    NIL])
  757.         
  758.         -> Create the 'File...' gadget
  759.         ng.topedge         := ng.topedge + 20
  760.         ng.gadgettext    := '_File...'
  761.         ng.gadgetid        := BUT_FILEREQ
  762.         but_filereq := gad := CreateGadgetA(BUTTON_KIND, gad, ng, 
  763.             [GT_UNDERSCORE,            "_",
  764.              NIL,                    NIL])
  765.         
  766.         -> Create the "Okay" gadget
  767.         ng.topedge        := (ng.topedge * 2)+13
  768.         ng.width        := ng.width / 3
  769.         ng.gadgettext    := '_Okay'
  770.         ng.gadgetid        := BUT_OKAYACT
  771.         but_okayact := gad := CreateGadgetA(BUTTON_KIND, gad, ng,
  772.             [GT_UNDERSCORE,            "_",
  773.              NIL,                    NIL])
  774.         
  775.         -> Create the "Remove" gadget
  776.         ng.leftedge        := ng.leftedge + (2*ng.width)
  777.         ng.gadgettext    := '_Delete this Action'
  778.         ng.gadgetid        := BUT_REMACT
  779.         but_remact := gad := CreateGadgetA(BUTTON_KIND, gad, ng,
  780.             [GT_UNDERSCORE,            "_",
  781.              NIL,                    NIL])
  782.         
  783.         -> Create the "Test" gadget
  784.         ng.topedge        := ng.topedge - 40
  785.         ng.gadgettext    := 'Test'
  786.         ng.gadgetid        := BUT_TESTACT
  787.         but_testact := gad := CreateGadgetA(BUTTON_KIND, gad, ng,
  788.             [GT_UNDERSCORE,         "_",
  789.              NIL,                    NIL])
  790. ENDPROC gad
  791.  
  792.     ->
  793.     -> load_config()
  794.     ->
  795.     -> This is not compatible with the IFX code, because it loads
  796.     -> everything into a different type of list, and sets different
  797.     -> global variables.
  798.     ->
  799.  
  800. PROC load_config() HANDLE
  801.     DEF file, buf, temp:PTR TO CHAR, done=0, list:PTR TO LONG
  802.     DEF ifx:PTR TO ifx_id, action:PTR TO ifx_action
  803.     DEF type
  804.     
  805.     -> Open the file
  806.     file := Open('s:IFX.ids', MODE_OLDFILE)
  807.     IF file
  808.         NEW buf[1024]
  809.         IF buf
  810.             WHILE done=0
  811.                 -> Read a line
  812.                 IF Fgets(file, buf, 1024)=NIL THEN done:=1
  813.                 
  814.                 -> Set string to lower case
  815.                 LowerStr(buf)
  816.                 
  817.                 -> Split the line into pieces
  818.                 list := argSplit(buf)
  819.                 IF list=NIL THEN Throw("MEM", ' (for arg list)')
  820.                 
  821.                 ->
  822.                 -> All types MUST be longer then 3 chars, otherwise
  823.                 -> they will be considered comments
  824.                 ->
  825.                 IF StrLen(list[0])>3
  826.                 
  827.                     -> Find type
  828.                     type := NIL
  829.                     IF StrCmp(list[0], 'sound')   THEN type    := ACT_SOUNDFILE
  830.                     IF StrCmp(list[0], 'exec')    THEN type    := ACT_EXECUTE
  831.                     IF StrCmp(list[0], 'other')   THEN type    := ACT_IFX
  832.                     IF StrCmp(list[0], 'defprefsdir')
  833.                         type := NIL            -> Prevent unnecessary pain
  834.                         IF last_dir=NIL        -> Only accept one
  835.                             -> Allocate memory
  836.                             NEW last_dir[StrLen(list[1]+1)]
  837.                             IF last_dir
  838.                                 StrCopy(last_dir, list[1])
  839.                             ELSE
  840.                                 put_error('Out of memory @ 808')
  841.                             ENDIF
  842.                         ENDIF
  843.                     ENDIF
  844.                     IF StrCmp(list[0], 'nothing') THEN type := -1
  845.                     
  846.                     IF type<>NIL
  847.                         -> Check if the ID already exists
  848.                         ifx := ids.findname(list[1])
  849.                         IF ifx=NIL THEN ifx := newid(list[1])
  850.                         
  851.                         -> Special case for type: ACT_NOTHING
  852.                         IF type=-1 THEN type := ACT_NOTHING        /* NIL */
  853.                         
  854.                         -> Add the entry
  855.                         IF list[2]
  856.                             -> Allocate the structure
  857.                             NEW action
  858.                             IF action=NIL THEN Throw("MEM", ' (for action data)')
  859.                             
  860.                             -> Get the data string
  861.                             NEW temp[StrLen(list[2])+1]
  862.                             IF temp=NIL THEN Throw("MEM", ' (for action string)')
  863.                             StringF(temp, '\s', list[2])
  864.                             action.name         := temp
  865.                             
  866.                             -> Set the type
  867.                             action.type            := type
  868.                             
  869.                             -> Add it to the list
  870.                             ifx.list.addtail(action)
  871.                         ENDIF
  872.                     ENDIF
  873.                 ENDIF
  874.                 
  875.                 -> Free the list
  876.                 DisposeLink(list)
  877.             ENDWHILE
  878.             
  879.             -> Free buffer
  880.             END buf
  881.         ELSE
  882.             Throw("MEM", ' (for read buffer)')
  883.         ENDIF
  884.         Close(file)
  885.     ELSE
  886.         Throw("INIT", "LOAD")
  887.     ENDIF
  888. EXCEPT
  889.     IF list THEN DisposeLink(list)
  890.     IF file THEN Close(file)
  891.     RETURN exception
  892. ENDPROC
  893.  
  894. PROC save_config() HANDLE
  895.     DEF file, buf:PTR TO CHAR, idname:PTR TO CHAR, actname:PTR TO CHAR
  896.     DEF ifx:PTR TO ifx_id, act:PTR TO ifx_action
  897.     DEF sel
  898.     
  899.     -> Error prevention
  900.     IF ids=NIL THEN RETURN -1
  901.     IF ids.is_empty() THEN RETURN NIL
  902.     
  903.     -> Open the file
  904.     file := Open('s:IFX.ids', MODE_NEWFILE)
  905.     IF file
  906.         -> Allocate a write buffer
  907.         NEW buf[1024]
  908.         IF buf
  909.             -> Write out our little header
  910.             StringF(buf, '*\n* IFX.ids    generated by:\n* IFX Preferences\n* © by Dobes Vandermeer\n*\n\ndefprefsdir \s', IF last_dir THEN last_dir ELSE 'RAM:')
  911.             Fputs(file, buf)
  912.             
  913.             -> Loop through all the ids and write them out
  914.             REPEAT
  915.                 -> Go to head id
  916.                 ifx := ids.head
  917.                 IF ifx=NIL THEN RETURN NIL
  918.                 
  919.                 -> Set up name string
  920.                 idname := ifx.name
  921.                 
  922.                 -> Write out a comment line
  923.                 StringF(buf, '#\n## ID: "\s"\n#\n', idname)
  924.                 Fputs(file, buf)
  925.                 
  926.                 -> Write out all the effects
  927.                 WHILE ifx.list.is_empty()=NIL
  928.                     act := ifx.list.head    -> Get head
  929.                     IF act=NIL THEN RETURN NIL    -> Bad list
  930.                     sel := act.type
  931.                     SELECT sel
  932.                         CASE ACT_SOUNDFILE
  933.                             actname := 'SOUND'
  934.                         CASE ACT_EXECUTE
  935.                             actname := 'EXEC'
  936.                         CASE ACT_IFX
  937.                             actname := 'OTHER'
  938.                         CASE ACT_NOTHING
  939.                             actname := 'NOTHING'
  940.                         DEFAULT
  941.                             actname := NIL
  942.                     ENDSELECT
  943.                     
  944.                     IF actname AND idname
  945.                         -> Write out the data
  946.                         StringF(buf, '\s "\s" "\s"\n', actname, idname, act.name)
  947.                         Fputs(file, buf)
  948.                     ENDIF
  949.                     
  950.                     -> Remove and destroy the action
  951.                     END act
  952.                 ENDWHILE
  953.                 
  954.                 -> Remove and destroy the id
  955.                 END ifx
  956.             UNTIL ids.is_empty()
  957.             -> Write out our little footer
  958.             StringF(buf, '*\n* END IFX.ids (generated by IFX Preferences)\n')
  959.         ENDIF
  960.         Close(file)
  961.     ELSE
  962.         Throw("SAVE", "OPEN")
  963.     ENDIF
  964. EXCEPT
  965.     IF file THEN Close(file)
  966.     IF buf THEN END buf
  967.     RETURN exception
  968. ENDPROC
  969.  
  970. ->
  971. -> ID functions
  972. ->
  973.  
  974. PROC newid(id:PTR TO CHAR) HANDLE
  975.     DEF ifx:PTR TO ifx_id
  976.     DEF list:PTR TO list
  977.     DEF temp:PTR TO CHAR
  978.     
  979.     -> Create the object
  980.     NEW ifx
  981.     IF ifx=NIL THEN Throw("MEM", ' (for new id)')
  982.     
  983.     NEW list.init()
  984.     IF list=NIL THEN Throw("MEM", ' (for new ids list)')
  985.     ifx.list := list
  986.     
  987.     -> Copy the ID
  988.     NEW temp[StrLen(id)+1]
  989.     IF temp
  990.         StringF(temp, '\s', id)
  991.         ifx.name := temp
  992.         ids.addtail(ifx)
  993.     ELSE
  994.         Throw("MEM", ' (for id string)')
  995.     ENDIF
  996. EXCEPT
  997.     IF ifx  THEN END ifx
  998.     IF list THEN END list
  999.     IF temp THEN END temp
  1000. ENDPROC ifx
  1001.  
  1002. ->
  1003. -> entrynum(l, n)
  1004. ->
  1005. -> Get entry "n" of the list "l"
  1006. ->
  1007.  
  1008. PROC entrynum(l:PTR TO list, num:LONG)
  1009.     DEF entry:PTR TO node
  1010.     DEF i
  1011.     -> Get the first entry
  1012.     entry := l.head
  1013.     
  1014.     -> Iterate to wanted entry
  1015.     FOR i := 1 TO num
  1016.         entry := entry.succ
  1017.     ENDFOR
  1018. ENDPROC entry
  1019.  
  1020.     ->
  1021.     -> do_action(ext)
  1022.     ->
  1023.  
  1024. PROC do_action(action:PTR TO ifx_action, ext=NIL)
  1025.     DEF type, data, temp
  1026.     DEF snd:PTR TO sound, tsnd:PTR TO sound
  1027.     DEF rexx:PTR TO rxobj
  1028.     
  1029.     -> Crash prevention
  1030.     IF str_info=NIL THEN RETURN
  1031.     IF act_curr=NIL THEN RETURN
  1032.     
  1033.     -> Assign our useful values here
  1034. ->    data := action.name
  1035.     data := str_info.specialinfo::stringinfo.buffer
  1036.     type := action.type
  1037.     
  1038.     SELECT type
  1039.         CASE ACT_NOTHING
  1040.             /* DO NOTHING */
  1041.         CASE ACT_AREXX
  1042.             -> ext=command, data=host
  1043.             NEW rexx.rxobj('IFX_ACTION')
  1044.             rexx.send(data, ext, NIL, NIL)
  1045.             END rexx      
  1046.         CASE ACT_EXECUTE
  1047.             -> data=string
  1048.             temp := Open('NIL:', MODE_NEWFILE)
  1049.             Execute(data, temp, temp)
  1050.         CASE ACT_SOUND
  1051.         CASE ACT_SOUNDFILE    
  1052.             NEW snd
  1053.             IF snd
  1054.                 IF snd.load(data)=NIL
  1055.                     -> If either of the sounds plays, we should wait for it
  1056.                     IF (snd.play(0)=NIL) OR (snd.play(1)=NIL)
  1057.                         Wait(snd.sigbits() OR SIGBREAKF_CTRL_C)
  1058.                     ENDIF
  1059.                 ENDIF
  1060.                 END snd
  1061.             ENDIF
  1062.             
  1063.         CASE ACT_IFX
  1064.             NEW temp[1024]
  1065.             StrCopy(temp, 'id ')
  1066.             StrAdd(temp, data)
  1067.             NEW rexx.rxobj('IFXPREFS_ACTION')
  1068.             rexx.send('PLAY', temp, NIL, NIL)
  1069.             END rexx      
  1070.             END temp
  1071.     ENDSELECT
  1072. ENDPROC
  1073.  
  1074. ->
  1075. -> put_error (str, win)
  1076. ->
  1077. -> output errors in an extensible way
  1078. ->
  1079.  
  1080. PROC put_error(str, win=NIL) IS EasyRequestArgs(win, 
  1081.                                 [SIZEOF easystruct, NIL, 'IFX Prefs Error', str, 'Okay'],
  1082.                                 NIL, NIL)
  1083.  
  1084. ->
  1085. -> ask(str, win)
  1086. ->
  1087. -> Ask user a yes or no question
  1088. ->
  1089.  
  1090. PROC ask(str, win=NIL) IS EasyRequestArgs(win,
  1091.                             [SIZEOF easystruct, NIL, 'IFX Preferences', str, 'Yes|No'],
  1092.                             NIL, NIL)
  1093.  
  1094. ->
  1095. -> Kill the listview's list
  1096. ->
  1097.  
  1098. PROC killlist(gad, win)
  1099.     IF gad THEN RETURN Gt_SetGadgetAttrsA(gad, win, NIL, [GTLV_LABELS, -1, NIL, NIL])
  1100. ENDPROC -1
  1101.  
  1102.     ->              <-
  1103.     -> ifx_#? PROCs <-
  1104.     ->              <-
  1105.  
  1106. PROC end() OF ifx_id
  1107.     self.remove()
  1108.     self.list.die()
  1109.     END self.list
  1110.     END self.name
  1111. ENDPROC
  1112.  
  1113.     ->
  1114.     -> Version string
  1115.     ->
  1116.     
  1117. vers: CHAR 0, '$VER: IFX Preferences 2.00', 0
  1118.